import { Alert, Button, Card, Space, Typography } from "antd";

import React, { useEffect, useRef, useState } from "react";

import "./index.less";

const { Title, Text } = Typography;

const Page50: React.FC = () => {
  const [isBlocking, setIsBlocking] = useState(false);
  const rafElementRef = useRef<HTMLDivElement>(null);
  const animationIdRef = useRef<number>();
  const startTimeRef = useRef<number>();

  // 模拟耗时的JS计算 - 阻塞主线程
  const blockMainThread = () => {
    setIsBlocking(true);
    const startTime = Date.now();

    // 执行一个耗时的计算，持续约300ms，并增加计算强度
    while (Date.now() - startTime < 300) {
      // 执行更多无意义的计算来消耗CPU
      for (let i = 0; i < 1000; i++) {
        Math.sqrt(Math.random() * 1000000);
        Math.sin(Math.random() * Math.PI);
        Math.cos(Math.random() * Math.PI);
      }
    }
    console.log("blockMainThread");
    setIsBlocking(false);
  };

  // 极端阻塞示例 - 阻塞主线程1秒
  const extremeBlock = () => {
    setIsBlocking(true);
    const startTime = Date.now();

    // 执行更长时间的计算，持续1秒
    while (Date.now() - startTime < 2000) {
      for (let i = 0; i < 5000; i++) {
        Math.sqrt(Math.random() * 1000000);
        Math.sin(Math.random() * Math.PI);
        Math.cos(Math.random() * Math.PI);
        JSON.stringify({ test: Math.random() });
        console.log("extremeBlock");
      }
    }

    setIsBlocking(false);
  };

  // 使用setTimeout的非阻塞版本
  const nonBlockingOperation = () => {
    console.log("nonBlockingOperation");
    setIsBlocking(true);

    // 使用setTimeout将工作分割成小块
    let count = 0;
    const maxCount = 100000;

    const doWork = () => {
      const batchSize = 1000;
      for (let i = 0; i < batchSize && count < maxCount; i++) {
        Math.sqrt(Math.random() * 1000000);
        count++;
      }

      if (count < maxCount) {
        setTimeout(doWork, 0); // 让出主线程
      } else {
        setIsBlocking(false);
      }
    };

    doWork();
  };

  // requestAnimationFrame 动画函数
  const animateWithRAF = (currentTime: number) => {
    if (!startTimeRef.current) {
      startTimeRef.current = currentTime;
    }

    const elapsed = currentTime - startTimeRef.current;
    const progress = (elapsed % 2000) / 2000; // 2秒一个周期

    if (rafElementRef.current) {
      // 创建复合动画：旋转 + 缩放 + 颜色变化
      const rotation = progress * 360;
      const scale = 1 + Math.sin(progress * Math.PI * 4) * 0.3; // 4次缩放周期
      const hue = progress * 360; // 颜色渐变

      rafElementRef.current.style.transform = `rotate(${rotation}deg) scale(${scale})`;
      rafElementRef.current.style.background = `hsl(${hue}, 70%, 60%)`;
    }

    animationIdRef.current = requestAnimationFrame(animateWithRAF);
  };

  // 启动和清理动画
  useEffect(() => {
    animationIdRef.current = requestAnimationFrame(animateWithRAF);

    return () => {
      if (animationIdRef.current) {
        cancelAnimationFrame(animationIdRef.current);
      }
    };
  }, []);

  return (
    <div className="page50-page">
      <Card>
        <Title level={2}>JS线程阻塞导致CSS动画卡顿演示</Title>

        <Alert
          message="观察说明"
          description="下面有CSS动画和requestAnimationFrame(RAF)动画对比。点击阻塞按钮时：CSS动画可能有轻微卡顿，但RAF动画会完全停止！点击非阻塞操作时，所有动画保持流畅。建议先点击'极端阻塞'按钮观察最明显的差异！"
          type="info"
          style={{ marginBottom: 24 }}
        />

        {/* 动画对比区域 */}
        <div className="animation-container">
          <div className="animation-section">
            <Text
              strong
              style={{ fontSize: 16, marginBottom: 12, display: "block" }}
            >
              CSS 动画 (由浏览器合成器处理)
            </Text>
            <div className="animation-row">
              <div className="rotating-box"></div>
              <div className="bouncing-ball"></div>
              <div className="sliding-bar"></div>
              <div className="pulsing-circle"></div>
            </div>
          </div>

          <div className="animation-section">
            <Text
              strong
              style={{ fontSize: 16, marginBottom: 12, display: "block" }}
            >
              requestAnimationFrame 动画 (依赖JS主线程)
            </Text>
            <div className="animation-row">
              <div ref={rafElementRef} className="raf-animation"></div>
            </div>
          </div>

          <Text type="secondary" style={{ marginTop: 16, display: "block" }}>
            当JS主线程被阻塞时，RAF动画会完全停止，而CSS动画受影响较小
          </Text>
        </div>

        <Space direction="vertical" style={{ width: "100%", marginTop: 24 }}>
          <Space wrap>
            <Button
              type="primary"
              danger
              onClick={blockMainThread}
              loading={isBlocking}
              disabled={isBlocking}
            >
              中等阻塞 (300ms)
            </Button>
            <Text type="secondary">执行同步计算，阻塞主线程约300ms</Text>
          </Space>

          <Space wrap>
            <Button
              type="primary"
              danger
              style={{ backgroundColor: "#ff4d4f", borderColor: "#ff4d4f" }}
              onClick={extremeBlock}
              loading={isBlocking}
              disabled={isBlocking}
            >
              极端阻塞 (1000ms)
            </Button>
            <Text type="secondary">执行密集计算，阻塞主线程1秒钟！</Text>
          </Space>

          <Space wrap>
            <Button
              type="primary"
              onClick={nonBlockingOperation}
              loading={isBlocking}
              disabled={isBlocking}
            >
              非阻塞操作
            </Button>
            <Text type="secondary">使用setTimeout分割任务，不阻塞主线程</Text>
          </Space>
        </Space>

        <Card style={{ marginTop: 24 }} size="small">
          <Title level={4}>技术原理：</Title>
          <ul>
            <li>
              <strong>60FPS标准：</strong>{" "}
              为了达到60FPS的流畅动画，每帧只有约16.6ms的时间
            </li>
            <li>
              <strong>主线程阻塞：</strong>{" "}
              当JS执行时间超过16.6ms时，会导致掉帧，动画出现卡顿
            </li>
            <li>
              <strong>解决方案：</strong>{" "}
              使用setTimeout、requestIdleCallback或Web
              Worker来避免长时间阻塞主线程
            </li>
            <li>
              <strong>CSS动画：</strong>{" "}
              CSS动画由浏览器的合成器线程处理，但仍会受到主线程阻塞的影响
            </li>
          </ul>
        </Card>
      </Card>
    </div>
  );
};

export default Page50;
